package cc.mrbird.febs.pay;

import cc.mrbird.febs.common.entity.PayConstant;
import cc.mrbird.febs.common.entity.Ret;
import cc.mrbird.febs.pay.base.PayModelFactory;
import cc.mrbird.febs.pay.enums.ALiTradeState;
import cc.mrbird.febs.pay.enums.PayType;
import cc.mrbird.febs.pay.model.PaymentParamPay;
import cc.mrbird.febs.payment.entity.PaymentInfo;
import cc.mrbird.febs.payment.service.IPaymentInfoService;
import com.alipay.easysdk.factory.Factory;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.formula.functions.T;
import org.checkerframework.checker.units.qual.K;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;


/**
 * @ClassName PaymentController
 * @Description
 * @Author 狗蛋儿
 * @Date 2021/1/21 15:12
 * @Version V1.0
 **/
@Slf4j
@Api(tags = {"支付服务"})
@RequestMapping("/payServe")
@RestController
public class PaymentController {

    //    @Autowired
//    private ALiPayBackTool aLiPayBackTool;
    @Autowired
    private IPaymentInfoService iPaymentInfoService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @ApiOperation(value = "支付宝APP支付", notes = "支付宝APP支付")
    @PostMapping("/ali/appPay")
    public Ret appPay(@RequestBody PaymentParamPay paymentParamPay) throws Exception {
        Map<String, String> stringStringMap = new HashMap<>();
        stringStringMap.put("orderSn", paymentParamPay.getOrderSn());
        stringStringMap.put("subject", paymentParamPay.getSubject());
        stringStringMap.put("totalAmount", paymentParamPay.getTotalAmount());

        String str = (String) PayModelFactory.getByPayType(PayType.A_LI_PAY_APP.getCode()).pay(stringStringMap);
        return Ret.success(str);
    }

    @ApiOperation(value = "支付宝取消订单【关闭交易】", notes = "支付宝取消订单【关闭交易】")
    @PostMapping("/ali/cancel")
    public Ret cancel(@RequestBody PaymentParamPay paymentParamPay) throws Exception {
        Map<String, String> stringStringMap = new HashMap<>();
        stringStringMap.put("orderSn", paymentParamPay.getOrderSn());
        String str = (String) PayModelFactory.getByPayType(PayType.A_LI_PAY_APP.getCode()).cancel(stringStringMap);
        return Ret.success(str);
    }

    @ApiOperation(value = "支付宝订单查询", notes = "支付宝订单查询")
    @PostMapping("/ali/queryPay")
    public Ret queryPay(@RequestBody PaymentParamPay paymentParamPay) throws Exception {
        Map<String, String> stringStringMap = new HashMap<>();
        stringStringMap.put("orderSn", paymentParamPay.getOrderSn());
        String str = (String) PayModelFactory.getByPayType(PayType.A_LI_PAY_APP.getCode()).queryPay(stringStringMap);
        return Ret.success(str);
    }

    @ApiOperation(value = "支付宝APP退款", notes = "支付宝APP退款")
    @PostMapping("/ali/appRefund")
    public Ret appRefund(@RequestBody PaymentParamPay paymentParam) throws Exception {
        Map<String, String> stringStringMap = new HashMap<>();
        stringStringMap.put("orderSn", paymentParam.getOrderSn());
        stringStringMap.put("refundAmount", paymentParam.getTotalAmount());
        String str = (String) PayModelFactory.getByPayType(PayType.A_LI_PAY_APP.getCode()).refund(stringStringMap);
        return Ret.success(str);
    }

    @ApiOperation(value = "支付宝PC支付", notes = "支付宝PC支付")
    @PostMapping("/ali/pcPay")
    public Ret pcPay(@RequestBody PaymentParamPay paymentParamPay) throws Exception {
        Map<String, String> stringStringMap = new HashMap<>();
        stringStringMap.put("orderSn", paymentParamPay.getOrderSn());
        stringStringMap.put("subject", paymentParamPay.getSubject());
        stringStringMap.put("totalAmount", paymentParamPay.getTotalAmount());
        String str = (String) PayModelFactory.getByPayType(PayType.A_LI_PAY_PC.getCode()).pay(stringStringMap);
        return Ret.success(str);
    }

    @ApiOperation(value = "支付宝退款订单查询", notes = "支付宝退款订单查询")
    @PostMapping("/ali/queryRefund")
    public Ret queryRefund(@RequestBody PaymentParamPay paymentParamPay) throws Exception {
        Map<String, String> stringStringMap = new HashMap<>();
        stringStringMap.put("orderSn", paymentParamPay.getOrderSn());
        String str = (String) PayModelFactory.getByPayType(PayType.A_LI_PAY_APP.getCode()).queryRefund(stringStringMap);
        return Ret.success(str);
    }




    /**
     * 支付异步回调
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "支付宝支付通知地址", notes = "支付宝支付通知地址")
    @PostMapping("/ali/aliPayNotify")
    public String aliPayNotify(HttpServletRequest request) {
        String result = "fail";
        try {

            log.info("进入支付宝支付异步回调");
            Map<String, String> params = getAllRequestParam(request);
            if (!Factory.Payment.Common().verifyNotify(params)) {
                log.info("校验失败");
                return result;
            }
            PaymentInfo paymentInfo = iPaymentInfoService.getPaymentInfoByOrderSn(params.get("out_trade_no"));
            if (Objects.isNull(paymentInfo)) {
                log.info("查询没有该订单");
                return result;
            }
            String totalAmount = params.get("total_amount");
            int totalAmountInt = new BigDecimal(totalAmount).multiply(BigDecimal.valueOf(100)).intValue();
            if (paymentInfo.getPayerTotal() != totalAmountInt) {
                log.info("金额校验失败");
                return result;
            }
            String sellerId = params.get("seller_id");
            String redisSellerId = stringRedisTemplate.opsForValue().get(PayConstant.SUFFIX + PayConstant.PAY_ALI_PAY_SELLER_ID);
            if (!StringUtils.equals(sellerId, redisSellerId)) {
                log.info("商户PID校验失败");
                return result;
            }
            String appId = params.get("app_id");
            String redisAAppId = stringRedisTemplate.opsForValue().get(PayConstant.SUFFIX + PayConstant.PAY_ALI_PAY_APP_ID);
            if (!StringUtils.equals(appId, redisAAppId)) {
                log.info("商户appId校验失败");
                return result;
            }
            String tradeStatus = params.get("trade_status");
            if (!StringUtils.equals(tradeStatus, ALiTradeState.TRADE_SUCCESS.getType())) {
                log.info("支付未成功");
                return result;
            }
//            for (Map.Entry<String, String> entry : params.entrySet()) {
//                log.info("key：{},value：{}", entry.getKey(), entry.getValue());
//            }
            log.info("校验【签名、订单号、金额、商户PID、商户appId、支付状态】通过");
            iPaymentInfoService.updatePaymentInfoForALiPay(paymentInfo, params);
            return "success";
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return result;
        }
    }


    private Map<String, String> getAllRequestParam(final HttpServletRequest request) {
        Map<String, String> res = new HashMap<>();
        Enumeration<?> temp = request.getParameterNames();
        while (temp.hasMoreElements()) {
            String en = (String) temp.nextElement();
            String value = request.getParameter(en);
            res.put(en, value);
        }
        return res;
    }


}
